﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using App.Core;
using App.Core.Entities;
using App.Core.Entities.Foundation;
using App.Core.Service;
using App.Core.Data;
using App.Core.Data.Repositories; 

namespace App.Service.Service
{
    public class BaseService<TEntity> : IService<TEntity> where TEntity : class
    {
        public IUnitOfWork unitOfWork { get; private set; }
        private readonly IRepository<TEntity> repository;
        private bool disposed { get; set; }

        public BaseService(IUnitOfWork unitOfWork)
        {
            this.unitOfWork = unitOfWork;
            this.repository = this.unitOfWork.Repository<TEntity>();
        }

        public IList<TEntity> GetAll()
        {
            return this.repository.GetAll();
        }

        public IList<TEntity> GetAll(Expression<Func<TEntity, bool>> predicate)
        {
            return this.repository.GetAll(predicate);
        }

        public Task<List<TEntity>> GetAllAsync(Expression<Func<TEntity, bool>> predicate)
        {
            return this.repository.GetAllAsync(predicate);
        }

        public IList<TEntity> GetByPager<TKey>(Expression<Func<TEntity, bool>> predicate, Expression<Func<TEntity, TKey>> orderBy, int pageIndex, int pageSize, bool isOrderByAsc = true) where TKey : struct
        {
            return this.repository.GetByPager<TKey>(predicate,orderBy,pageIndex,pageSize,isOrderByAsc);
        }
        public Task<List<TEntity>> GetByPagerAsync<TKey>(Expression<Func<TEntity, bool>> predicate, Expression<Func<TEntity, TKey>> orderBy, int pageIndex, int pageSize, bool isOrderByAsc = true) where TKey : struct
        {
            return this.repository.GetByPagerAsync<TKey>(predicate,orderBy,pageIndex,pageSize,isOrderByAsc);
        }

        public TEntity FirstOrDefault(Expression<Func<TEntity, bool>> predicate)
        {
            return this.repository.FirstOrDefault(predicate);
        }
        public Task<TEntity> FirstOrDefaultAsync(Expression<Func<TEntity, bool>> predicate)
        {
            return this.repository.FirstOrDefaultAsync(predicate);
        }

        public TEntity Add(TEntity entity)
        {
            repository.Add(entity);
            unitOfWork.Commit();

            return entity;
        }

        public async Task<TEntity> AddAsync(TEntity entity)
        {
            repository.Add(entity);
            await unitOfWork.CommitAsync(); 
            return entity;
        }

        public int Count()
        {
            return repository.Count();
        }

        public Task<int> CountAsync()
        {
            return repository.CountAsync();
        }

        public void Delete(TEntity entity)
        {
            repository.Delete(entity);
            unitOfWork.Commit();
        }

        public Task DeleteAsync(TEntity entity)
        {
            repository.Delete(entity);
            return unitOfWork.CommitAsync();
        }

        public Task<List<TEntity>> GetAllAsync()
        {
            return repository.GetAllAsync();
        } 

        public void Update(TEntity entity)
        {
            repository.Update(entity);
            unitOfWork.Commit();
        }

        public Task UpdateAsync(TEntity entity)
        {
            repository.Update(entity);
            return unitOfWork.CommitAsync();
        }

        public Task<int> CountAsync(Expression<Func<TEntity, bool>> predicate)
        {
            return repository.CountAsync(predicate);
        }
        public int Count(Expression<Func<TEntity, bool>> predicate)
        {
            return repository.Count(predicate);
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        public virtual void Dispose(bool disposing)
        {
            if (!disposed && disposing)
            {
                unitOfWork.Dispose();
            }
            disposed = true;
        }

        
    }
}
